<template>
  <div class="ek-select">
    <el-select 
      v-model="value" 
      filterable
			@blur="blur" 
			@focus="focus"
			@change="change" 
			@clear="clear"
			:loading="loading" 
			loading-text="加载中"
			no-data-text="无数据"
      :placeholder="placeholder"
      :disabled="disabled"
      :clearable="clearable"
      :multiple="multiple"
      :collapse-tags="collapseTags"
      :collapse-tags-tooltip="collapseTagsTooltip"
      :size="size"
      :empty-values="[null]"
      :value-on-clear="null"

		>
			<el-option
				v-for="item in ekOptions"
				:key="item.value"
				:label="item.label"
				:value="item.value"
			/>
    </el-select>
  </div>
</template>

<script setup>

import {
  nextTick,
  defineComponent,
  defineEmits,
  onMounted,
  getCurrentInstance,
  computed,
  ref,
  watch,
  reactive
} from "vue";
import { getDimensionByCode } from "@/utils/sys.js";

const props = defineProps({
  modelValue: {
    type: [String, Number, Array, Boolean],
    default: "",
  },
  // 显示名称
  name: {
    type: [String, Array],
    default: "",
  },
  // 禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 是否显示清除
  clearable: {
    type: Boolean,
    default: true,
  },
  // 默认显示
  placeholder: {
    type: String,
    default: "请选择",
  },
  // 初始化请求接口
  autoInit:{
    type: Boolean,
    default: false,
  },
  // 维度编码，存在则直接查询维度接口，优先级比url高
  dimCode: {
    type: String,
    default: '',
  },
  // 远程地址,存在远程地址
  url: {
    type: String,
    default: '',
  },
  //选项，选项里面必须包含label和value
  options: {
    type: Array,
    default: () => [],  
  },
  // 是否多选
  multiple:{
    type: Boolean,
    default: false,
  },
  // 多选是否折叠
  collapseTags: {
    type: Boolean,
    default: true,
  },
  collapseTagsTooltip: {
    type: Boolean,
    default: true,
  },
  // 字段映射
  mapping: {
    type: Object,
    default: () => ({
      label: ['label'],
      value: "value"
    }),
  },
  size: {
    type: String,
    default: 'default'
  },
  // 空值
  emptyValues: {
    type: Array,
    default: () => [''],
  },
});

const {
  appContext: {
    config: { globalProperties },
  }
} = getCurrentInstance();

const { $http } = globalProperties;

const emit = defineEmits(["update:modelValue",'blur','focus','change','clear'])


const value = computed({
  get() {
    if(props.multiple){
      return  props.modelValue;
    }else {
      return props.modelValue
    }
  },
  set(value) {
    if(props.multiple){
      emit('update:modelValue', value)
    } else {
      emit('update:modelValue', value)
    }
  }
})
const url =  computed(() => {
  if(props.url || props.dimCode){
    return props.url || props.dimCode
  } else {
    return ''
  }
})

// 选项列表
const ekOptions =  computed(() => {
  if(url.value){
    return remoteData.value;
  } else {
    return props.options
  }
});

// 加载中
let loading = ref(false)
// 是否已经加载过
let loaded = ref(false)
function init(isFocus = false) {
  // 存在远程地址，开启初始化获取数据或者存在值
  if(url.value){
    // 聚焦，开始初始化， 或者存在值且name为空，则直接执行获取数据
    if(isFocus || 
    props.autoInit  || 
    ((!props.multiple && (value.value  || value.value === 0 ) && !props.name) || 
    ( props.multiple && value.value?.length && !props.name?.length ))) {
      getData(url.value);
    }  else {
      if(props.multiple) {
        for(let i = 0; i < value.value.length; i++){
          remoteData.value.push({
            label: props.name[i],
            value: value.value[i],
          })
        }
      } else {
        remoteData.value.push({
          label: props.name,
          value: value.value,
        })
      }
    }
  }
}
// 获取远程数据
const remoteData = ref([]);
// 获取下拉列表
async function getData(url) {
  // 加载中或者是，已经加载过了直接返回
	if(loaded.value || loading.value){
		return;
	}
  loading.value = true;
  let list = null;
  if(props.dimCode){
    list = await getDimensionByCode(props.dimCode);
  } else {
    let res = await $http.get(url);
    if(res.status === 'success'){
      list = res.data?.length?  res.data : [];
    }
  }
  if(list?.length){
    remoteData.value = setMappingData(props.mapping, list);
  }
  loaded.value = true
  loading.value = false;

}


// 失去焦点
function blur(event) {
  emit("blur", event);
};
// 聚焦
function focus(event) {
  init(true);
  emit("focus", event);
};
// 改变事件, 清空会返回undefined
function change( event ) {
  emit("change", event);
};
// 清除事件
function clear() {
  emit("clear");
};

function setMappingData(mapping, data){
    for(let j in data){
      let item = data[j];
      item['value'] = item[mapping['value']]
      let labelArr = [];
      for(let i in mapping['label']){
        labelArr.push(item[mapping['label'][i]]);
      }
      item['label'] = labelArr.join('-');
    }
    return data
}
onMounted(() => {
  init(false);
})


// todo 如果初始化不请求数据如何回显问题
</script>

<style scoped lang="scss"></style>
